package com.xyy.saas.payment.callback.core.handler;

import com.alibaba.fastjson.JSON;
import com.xyy.saas.payment.callback.core.result.CallbackRunner;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.adpater.pingxx.domain.PayDO;
import com.xyy.saas.payment.dao.mapper.PrePayOrderMapper;
import com.xyy.saas.payment.dao.model.PayResultOrder;
import com.xyy.saas.payment.dao.model.PrePayOrder;
import com.xyy.saas.payment.service.PayResultOrderService;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.SkyWalkingMonitorUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

/**
 * @author wangtianqi
 * 处理charge支付成功回调
 *
 */
@Component
public class PaySuccessHandler implements BaseHandler {

    private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(PaySuccessHandler.class);

    @Autowired
    private PrePayOrderMapper prePayOrderMapper;
    @Autowired
    private CallbackRunner callbackRunner;
    @Resource
    private SkyWalkingMonitorUtil skyWalkingMonitorUtil;
    @Autowired
    private PayResultOrderService payResultOrderService;

    @Override
    public String getMethod() {
        return Constants.METHOD_PAY_SUCCESS_NAME;
    }

    @Override
    public boolean callBackHandler(Object domain) {
        Date startTime = DateUtil.now();
        LOGGER.info("PaySuccessHandler#callBackHandler payDO:{}", JSON.toJSONString(domain));
        PayDO payDO = (PayDO) domain;
        payDO.setNotifyTime(DateUtil.now());

        if(StringUtils.isEmpty(payDO.getOrderNo())) {
            LOGGER.error("PaySuccessHandler#callBackHandler wxpay callback fail domain is null");
            return false;
        }

        // 校验是否成功
        if (!"SUCCESS".equals(payDO.getResultCode())) {
            LOGGER.error("PaySuccessHandler#callBackHandler error ResultCode is FAIL payDO:{}", JSON.toJSON(payDO));
            return true;
        }

        // 校验预支付单是否存在
        PrePayOrder prePayOrder = prePayOrderMapper.getPrePayOrderByPayNo(payDO.getOrderNo());

        if(prePayOrder == null) {
            LOGGER.error("PaySuccessHandler#callBackHandler order not exit error orderNo:{}", payDO.getOrderNo());
            return false;
        }

        // 检验订单金额
        if(!payDO.getAmount().equals(prePayOrder.getAmount())) {
            // 回调进来的金额和发起订单金额不等
            LOGGER.error("PaySuccessHandler#callBackHandler callback amount error  payDo:{} pay:{}", JSON.toJSONString(payDO), JSON.toJSONString(prePayOrder));
            return false;
        }

        // 幂等判断
        PayResultOrder payResultOrder = payResultOrderService.selectByPayNoAndChannel(payDO.getOrderNo(), payDO.getChannel());

        if(payResultOrder != null && Objects.equals(payResultOrder.getPayChannel(), payDO.getChannel())) {
            LOGGER.error("PingXXCallback callBackHandler callBackHandler repeat payNo:{}", payDO.getOrderNo());
            return true;
        }

        payDO.setBusinessType(prePayOrder.getBusinessType());
        payDO.setBusinessOrderType(prePayOrder.getBusinessOrderType());
        payDO.setReceiverId(prePayOrder.getReceiverId());
        payDO.setCallbackAddress(prePayOrder.getCallbackAddress());
        payDO.setPayer(prePayOrder.getPayer());
        payDO.setCount(0);
        payDO.setBusinessOrderNo(prePayOrder.getBusinessOrderNo());
        callbackRunner.callbackPingXX(payDO);

        // 渠道回调时间监控
        if(!payDO.getChannel().contains(Constants.CHANNEL_UNIONPAY_NAME)) {
            skyWalkingMonitorUtil.summary(SkyWalkingMonitorUtil.CALLBACK_CHANNEL_COST_PREFIX + payDO.getChannel(),
                    DateUtil.getTimeDiff(payDO.getTimePaid(), startTime));
        }

        return true;
    }
}
